﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Com.FastSearch.SharePoint.BL.SearchManager;
using Com.FastSearch.SharePoint.Interfaces;
using Com.FastSearch.Utils;
using Microsoft.SharePoint;

namespace Com.FastSearch.SharePoint.WebControls.ESPSearchWebParts.UI.Editors
{
    internal class ESPSearchActionEditorPart : EditorPart
    {
        #region Constants


        #endregion

        #region Class variables
        private List<ISortField> _sortFields;
        private Dictionary<String, DropDownList> sortFieldsSortingDict;
        private Dictionary<String, CheckBox> sortFieldsDict;
        private Dictionary<String, TextBox> sortFieldsDisplayNameDict;

        private readonly string _view;        
        private string _ErrorMessageSort = null;       
        private Table editTable = new Table();        

        #endregion

        public ESPSearchActionEditorPart(string view)
        {
            _view = view;
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            try
            {
                _sortFields = GetSortFields();                
            }
            catch (Exception)
            {
                _sortFields = new List<ISortField>();
            }
        }

        public override bool ApplyChanges()
        {
            ESPSearchAction espAction = WebPartToEdit as ESPSearchAction;
            if (espAction != null)
            {
                EnsureChildControls();

                List<SearchSortAction> sortList = new List<SearchSortAction>();
                

                foreach (KeyValuePair<string, CheckBox> pair in sortFieldsDict)
                {
                    string key = pair.Key;

                    CheckBox checkbox = pair.Value;
                    if (checkbox.Checked)
                    {

                        SearchSortAction ssaction = new SearchSortAction(key);
                        if (sortFieldsDisplayNameDict.ContainsKey(key))
                        {
                            string name = sortFieldsDisplayNameDict[key].Text;
                            if (!string.IsNullOrEmpty(name))
                            {
                                ssaction.DisplayName = name;
                            } else
                            {
                                ssaction.DisplayName = key;    
                            }
                        }

                        if (sortFieldsSortingDict.ContainsKey(key))
                        {
                            DropDownList sortDirection = sortFieldsSortingDict[key];
                            if (sortDirection.SelectedIndex == 0)
                            {
                                ssaction.DefaultSortOrder = SortOrderEnum.Ascending;
                            } else
                            {
                                ssaction.DefaultSortOrder = SortOrderEnum.Descending;
                            }
                        } else
                        {
                            ssaction.IsRankProfile = true;
                        }                                                
                        sortList.Add(ssaction);
                    }
                }
                espAction.SearchSortActions = ESPSearchAction.BuildStringFromList(sortList);
            }
            return (espAction != null);
        }
      
        public override void SyncChanges()
        {
            ESPSearchAction espAction = WebPartToEdit as ESPSearchAction;
            if (espAction != null)
            {
                EnsureChildControls();

                ICollection<SearchSortAction> searchSortActions = ESPSearchAction.BuildListFromString(espAction.SearchSortActions);
                if (searchSortActions != null)
                {                
                    foreach (SearchSortAction action in searchSortActions)
                    {                        
                        SyncFieldChange(action, true, true);
                    }
                }    

                // Disable the select box for the default sorting            
                SearchSortAction defaultSortAction = null;
                if (!string.IsNullOrEmpty(espAction.SearchRequest.ResultSorting))
                {
                    defaultSortAction =
                           ESPSearchAction.GetSortActionFromSortString(espAction.SearchRequest.ResultSorting, true);

                    if (defaultSortAction != null && sortFieldsDict.ContainsKey(defaultSortAction.FieldName)) {
                        SyncFieldChange(defaultSortAction, false, false);                        
                    }
                }                                
            }
        }

        private void SyncFieldChange(SearchSortAction action, bool enableSelect, bool updateText)
        {
            string fieldName = action.FieldName;
            if (sortFieldsDict.ContainsKey(fieldName))
            {
                CheckBox checkbox = sortFieldsDict[fieldName];
                checkbox.Checked = true;
                checkbox.Enabled = enableSelect;
            }

            if (sortFieldsSortingDict.ContainsKey(fieldName))
            {
                DropDownList dropDown = sortFieldsSortingDict[fieldName];
                            
                if (action.DefaultSortOrder == SortOrderEnum.Ascending)
                {
                    dropDown.SelectedIndex = 0;
                } else
                {
                    dropDown.SelectedIndex = 1;
                }
                dropDown.Enabled = enableSelect;   
            }

            if (updateText)
            {
                if (sortFieldsDisplayNameDict.ContainsKey(fieldName))
                {
                    TextBox tb = sortFieldsDisplayNameDict[fieldName];
                    tb.Text = action.DisplayName;
                }
            }
        }


        /// <summary>
        /// Return a string array containing the sort direction in pos 0 and the field name in pos 1
        /// NOTE: For now only one single sorting is implemented.        
        /// </summary>
        /// <param name="sortString"></param>
        /// <returns></returns>
        private string[] GetSorting(string sortString)
        {
            if (sortString == null)
            {
                return new string[] {"+", "default"};
            }

            sortString = sortString.Trim();
            if ((sortString[0].Equals("+")) || (sortString[0].Equals("-")))
            {
                return new string[] {sortString.Substring(0, 1), sortString.Substring(1)};
            }
            else
            {
                return new string[] {"+", sortString};
            }
        }
        
        private static void AddToEditSection(Table table1, Control editSection)
        {
            TableRow tr = new TableRow();
            TableCell tc = new TableCell();
            table1.Rows.Add(tr);
            tr.Cells.Add(tc);
            tc.Controls.Add(editSection);    
        }

     
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
                        
            editTable = new Table();
            
            // Sort Fields
            Table table = new Table();
            CreateSortFieldsBody(table);            
            AddToEditSection(editTable, table);

            Controls.Add(editTable);            
        }

        private static void CreatedConfigTableRow(Table table, TableRow row, TableCell cell1, TableCell cell2, string label, string tooltip)
        {
            if (!String.IsNullOrEmpty(label))
            {
                TableHeaderRow thr = new TableHeaderRow();
                thr.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Left;
                table.Rows.Add(thr);
                TableHeaderCell tc = new TableHeaderCell();
                tc.ColumnSpan = 2;
                tc.Controls.Add(CreateLabel(label, tooltip, "UserSectionHead"));
                thr.Cells.Add(tc);
                table.Rows.Add(thr);
            }

            table.Rows.Add(row);
            row.Cells.Add(cell1);
            if (cell2 == null)
            {
                cell1.ColumnSpan = 2;
            }
            else
            {
                row.Cells.Add(cell2);
            }
        }

        public void CreateSortFieldsBody(Table table)
        {
            // Build the sort fields and sort directions
            sortFieldsDict = new Dictionary<string, CheckBox>();
            sortFieldsSortingDict = new Dictionary<string, DropDownList>();            
            sortFieldsDisplayNameDict = new Dictionary<string, TextBox>();

            foreach (ISortField sortField in _sortFields)
            {
                TextBox tb = new TextBox();
                tb.Text = sortField.FieldName;
                sortFieldsDisplayNameDict.Add(sortField.FieldName, tb);
                CheckBox checkBox = new CheckBox();
                checkBox.Text = sortField.FieldName;
                sortFieldsDict.Add(sortField.FieldName, checkBox);
                if (!sortField.IsRankField)
                {
                    DropDownList dropDownList = new DropDownList();
                    dropDownList.Items.Add("Ascending");
                    dropDownList.Items.Add("Descending");
                    sortFieldsSortingDict.Add(sortField.FieldName, dropDownList);                    
                }                
            }
            
            // Create the output
            TableCell leftcell = new TableCell();
            TableCell rightcell = new TableCell();
            CreatedConfigTableRow(table, new TableRow(), leftcell, rightcell, "Available custom sorting", null);            
            leftcell.Controls.Add(CreateLabel("Sort Fields to display", "Specify the sort fields which should be shown to the user"));

            Table tbl = new Table();
            foreach (KeyValuePair<string, CheckBox> pair in sortFieldsDict)
            {
                TableRow tblRow = new TableRow();
                TableCell tblCell = new TableCell();
                TableCell tblCellSortDirection = new TableCell();
                TableCell tblCellNamin = new TableCell();
                if (sortFieldsSortingDict.ContainsKey(pair.Key))
                {
                    tblCellSortDirection.Controls.Add(sortFieldsSortingDict[pair.Key]);                                        
                }
                tblCellNamin.Controls.Add(sortFieldsDisplayNameDict[pair.Key]);    
                tblRow.Cells.Add(tblCell);
                tblRow.Cells.Add(tblCellNamin);
                tblRow.Cells.Add(tblCellSortDirection);
                tbl.Rows.Add(tblRow);
                tblCell.Controls.Add(pair.Value);
            }
            rightcell.Controls.Add(tbl);                        
            if (_ErrorMessageSort != null)
            {
                AddErrorMessage(table, _ErrorMessageSort);
            }            
        }

        protected static Label CreateLabel(string labelText, string toolTip)
        {
            return CreateLabel(labelText, toolTip, null);
            
        }

        protected static Label CreateLabel(string labelText, string toolTip, string cssClass)
        {
            Label lb = new Label();
            lb.Text = labelText;
            if (!String.IsNullOrEmpty(cssClass) )
            {
                lb.CssClass = cssClass;
            }
            if (toolTip != null)
            {
                lb.ToolTip = toolTip;
            }
            return lb;
        }        

        private void AddErrorMessage(Table table, string message)
        {            
            Label errorMessage = new Label();
            errorMessage.Text = message;
            errorMessage.ApplyStyle(Zone.ErrorStyle);
            TableCell cell1 = new TableCell();
            CreatedConfigTableRow(table, new TableRow(), cell1, null, null, null);
            cell1.Controls.Add(errorMessage);                        
        }       

        private static IESPSearchManagerFactory GetSearchManagerFactory()
        {
            return SimpleFactoryManager<IESPSearchManagerFactory>.Factory;
        }

        private IESPSearchManager GetSearchManager()
        {
            IESPSearchManagerFactory fact = GetSearchManagerFactory();
            
            ESPSearchAction espAction = WebPartToEdit as ESPSearchAction;
            // Check if an esp custom connection is used
            if (espAction != null && !String.IsNullOrEmpty(espAction.SearchRequest.ESPConnection))
            {
                return fact.Create(espAction.SearchRequest.ESPConnection);
            }            
            return fact.Create(SPContext.Current.Site.WebApplication);
        }        
        private List<ISortField> GetSortFields()
        {
            try
            {
                IESPSearchManager sm = GetSearchManager();
                return sm.GetSortableFieldsAndRankProfiles(_view);
            }
            catch (Exception)
            {
                _ErrorMessageSort = "Sorting Fields could not be retrieved from ESP Search!";
            }
            return new List<ISortField>();
        }
    }
}